package com.phrp.service.impl;

import com.phrp.common.ConstantEnum;
import com.phrp.common.ConstantNumber;
import com.phrp.entity.ManagerUser;
import com.phrp.entity.vo.ManagerUserSearchDataVo;
import com.phrp.entity.vo.PageData;
import com.phrp.exception.CustomizationException;
import com.phrp.util.returnResult.ReturnInfoEnum;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.phrp.dao.ManagerUserDao;
import com.phrp.util.returnResult.ResponseResult;
import com.phrp.service.ManagerUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;


/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author ssc
 * @since 2024-04-06
 */
@Service
public class ManagerUserserviceImpl extends ServiceImpl<ManagerUserDao, ManagerUser> implements ManagerUserService {
    @Autowired
    private ManagerUserDao managerUserDao;




    /*
        @Transactional注解：Spring框架用来管理事务的注解，可以在类上或方法上使用，如下
            1. 在方法上使用：指定适当的事务传播行为和隔离级别。
                可以使用propagation属性来指定事务的传播行为，例如
                    Propagation.REQUIRED表示如果当前存在事务，则加入该事务，否则创建一个新的事务；
                可以使用功isolation属性来指定事务的隔离级别，例如
                    Isolation.READ_COMMITTED表示可以读取到已经提交的数据，但不能读取到其他事务未提交的数据；
                指定事务的回滚规则，可以使用rollbackFor属性来制定那些异常触发事务回滚，例如
                    rollbackFor = Exception.class表示遇到任何异常都会触发事务回滚。
            2. 在类级别上使用：类中的所有公共方法都会受到事务管理，可以覆盖方法级别的注解，如果同时拥有，则以方法的优先级高。
     */

    /**
     * 增加用户
     * @param managerUser
     * @return
     */
    @Transactional(rollbackFor = CustomizationException.class)
    @Override
    public ResponseResult addManagerUser(ManagerUser managerUser) {
        // 获取UUID
        UUID uuid = UUID.randomUUID();
        managerUser.setMUuid(uuid.toString().replace("-", ""));

        // 修改密码，进行加密，第一个是加密密码，第二个是盐值（这里使用phone），第三个是加密次数
        Md5Hash md5Pwd = new Md5Hash("123456", managerUser.getPhone(), 1024);
        // toHex方法将字节数组转换为进制字符串
        managerUser.setPassword(md5Pwd.toHex());

        // 将用户写入
        int insert = managerUserDao.insert(managerUser);

        if (insert != 1) {
            // 数据库写入错误
            throw new CustomizationException(ReturnInfoEnum.DATA_FAIL);
        }
        return new ResponseResult(ReturnInfoEnum.SUCCESS);
    }

    /**
     * 更新状态
     * @param id
     * @param status
     * @return
     */
    @Override
    public ResponseResult updateStatus(String id, String status) {
        UpdateWrapper<ManagerUser> update = new UpdateWrapper<>();
        update.eq("m_uuid",id)
                .set("status",status);

        int i = managerUserDao.update(null, update);

        if(i != 1){
            throw new CustomizationException(ReturnInfoEnum.DATA_FAIL);
        }

        return new ResponseResult<>(ReturnInfoEnum.SUCCESS);
    }

    /**
     * 获取巡查员的数据信息
     * @param inspectorSearch
     * @return
     */
    @Override
    public ResponseResult getInspector(ManagerUserSearchDataVo inspectorSearch) {
        QueryWrapper<ManagerUser> query = new QueryWrapper<>();
        if(inspectorSearch.getMUuid() != null && inspectorSearch.getMUuid() != ""){
            query.like("m_uuid",inspectorSearch.getMUuid());
        }
        query.between("inspection_number",0, ConstantNumber.INSPECTION_MAX-1)
                .eq("position", ConstantEnum.POSITION.getCode())
                .select("m_uuid","name","dictionary_query('manager_user','sex',sex) sex","age")
                .orderByAsc("inspection_number")
                .orderByDesc("create_time");

        Page<ManagerUser> page = new Page(inspectorSearch.getCurrentPage(),inspectorSearch.getPageSize());
        Page<ManagerUser> managerUserPage = managerUserDao.selectPage(page, query);

        PageData<List<ManagerUser>> pageData = new PageData<>();
        pageData.setData(managerUserPage.getRecords());
        pageData.setTotalNumber(managerUserPage.getTotal());

        return new ResponseResult(ReturnInfoEnum.SUCCESS,pageData);
    }

    /**
     * 获取用户信息
     * @return
     */
    @Override
    public ResponseResult<ManagerUser> personMessage() {
        // 由于在realm验证中已经将信息给返回到安全管理器中了，我就可以直接进入上下文获取用户信息并返回，
        // 就不需要HttpServletRequest request去获取token
        Subject subject = SecurityUtils.getSubject();
        ManagerUser mUser = (ManagerUser) subject.getPrincipal();
        return new ResponseResult<>(ReturnInfoEnum.SUCCESS,mUser);
    }

    /**
     * 通过手机号获取用户的信息
     *
     * @param phone
     * @return
     */
    @Override
    public ManagerUser getByPhone(String phone) {
        ManagerUser mUser = managerUserDao.getByPhone(phone);
        return mUser;
    }

    /**
     * 检验token是否有效，有效则返回200
     * @param
     * @return
     */
    @Override
    public ResponseResult tokenCheck() {
        return new ResponseResult(ReturnInfoEnum.SUCCESS);
    }

    /**
     * 修改用户信息
     * @param mUser
     * @return
     */
    @Transactional(rollbackFor = CustomizationException.class)
    @Override
    public ResponseResult changeMessage(ManagerUser mUser) {
        UpdateWrapper updateWrapper = new UpdateWrapper();
        updateWrapper.eq("phone",mUser.getPhone());
        int i = managerUserDao.update(mUser, updateWrapper);

        // 数据库写入错误
        if(i != 1){
            throw new CustomizationException(ReturnInfoEnum.DATA_FAIL);
        }
        return new ResponseResult(ReturnInfoEnum.SUCCESS);
    }

    /**
     * 修改密码
     * @param message
     * @return
     */
    @Override
    public ResponseResult changePwd(ManagerUser message) {
        // 首先对密码进行加密
        Md5Hash md5Hash = new Md5Hash(message.getPassword(),message.getPhone(),1024);

        message.setPassword(md5Hash.toHex());

        // 获取经过token获取到的用户数据
        Subject subject = SecurityUtils.getSubject();
        ManagerUser mUser = (ManagerUser) subject.getPrincipal();

        // 进行两次密码判断是否一致
        if(mUser.getPassword().equals(md5Hash.toHex())){
            // 表示前后密码相同
            return new ResponseResult(ReturnInfoEnum.PASSWORD_EQUALS);
        }

        // 两次密码不想等，写入密码

        UpdateWrapper updateWrapper = new UpdateWrapper();
        updateWrapper.eq("phone",message.getPhone());

        int i = managerUserDao.update(message, updateWrapper);

        // 数据库操作出现错误，抛出异常
        if(i != 1){
            throw new CustomizationException(ReturnInfoEnum.DATA_FAIL);
        }

        return new ResponseResult(ReturnInfoEnum.SUCCESS);
    }

    /**
     * 搜索管理人员数据
     * @param searchData
     * @return
     */
    @Override
    public ResponseResult searchManagerUsers(ManagerUserSearchDataVo searchData) {
        searchData.setStartPage((searchData.getCurrentPage()-1) * searchData.getPageSize());

        LinkedList<ManagerUser> list = managerUserDao.selectBySearchData(searchData);

        Integer totalNum = managerUserDao.selectTotalBySearchData(searchData);

        PageData<LinkedList<ManagerUser>> pageData = new PageData<>();

        pageData.setData(list);

        pageData.setTotalNumber(totalNum);

        return new ResponseResult(ReturnInfoEnum.SUCCESS,pageData);
    }

    /**
     * 重置用户密码
     * @param managerUsers
     * @return
     */
    @Transactional(rollbackFor = CustomizationException.class)
    @Override
    public ResponseResult resetPassword(LinkedList<ManagerUser> managerUsers) {
        // 遍历ID
        for (ManagerUser user : managerUsers) {
            Md5Hash md5Hash = new Md5Hash("123456",user.getPhone(),1024);
            String password = md5Hash.toHex();
            int i = managerUserDao.updatePwdById(user.getMUuid(),password);
            if(i != 1){
                throw new CustomizationException(ReturnInfoEnum.DATA_FAIL);
            }
        }

        return new ResponseResult(ReturnInfoEnum.SUCCESS);
    }

    /**
     * 修改职位信息
     * @param id
     * @param position
     * @return
     */
    @Override
    public ResponseResult changePosition(String id, String position) {
        UpdateWrapper<ManagerUser> update = new UpdateWrapper();
        update.eq("m_uuid",id)
                .set("position",position);

        int i = managerUserDao.update(null, update);

        if(i != 1){
            throw new CustomizationException(ReturnInfoEnum.DATA_FAIL);
        }
        return new ResponseResult(ReturnInfoEnum.SUCCESS);

    }

    /**
     * 删除用户信息
     * @param ids
     * @return
     */
    @Transactional(rollbackFor = CustomizationException.class)
    @Override
    public ResponseResult deleteManagerUser(LinkedList<String> ids) {
        int i = managerUserDao.deleteBatchIds(ids);

        if(i != ids.size()){
            // 删除出错
            throw new CustomizationException(ReturnInfoEnum.DATA_FAIL);
        }

        return new ResponseResult(ReturnInfoEnum.SUCCESS);
    }
}
